#include "solar/trunk/NbaseWin.h"

NMainWindow::NMainWindow(QWidget *parent) : QMainWindow(parent, QMainWindow().windowFlags() |
                                                                Qt::FramelessWindowHint |
                                                                Qt::WindowMinimizeButtonHint)
,win_radius(4)
,margin_touch_type(NT::LOCALTION_UNVALID)
,rvs_scount(0) // show opacity addtion
,rvs_hcount(10) // hide opacity addtion
,rvs_sinteval(70) // show inteval
,rvs_hinteval(25) // hide inteval
,exp_sinteval(20)
,win_cornered(4)
,linear_backtime(300)
{
    TT_Object->setFixedHeight(29);
    setAttribute(Qt::WA_DeleteOnClose);
    setAttribute(Qt::WA_TranslucentBackground);
    d_margin_radius(QMargins(0,0,0,0), win_radius);
    stretchTimer.setSingleShot(true);
    stretchTimer.setInterval(exp_sinteval);

    HMONITOR hMonitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTONEAREST);
    MONITORINFO mi;
    mi.cbSize = sizeof(mi);
    GetMonitorInfo(hMonitor, &mi);
    tagRECT globalArea = mi.rcWork;
    tagRECT taskbar_Area = mi.rcMonitor;
    taskbar_height = taskbar_Area.bottom - globalArea.bottom;
    View_hoverMask->taskbar_height = taskbar_height;
    move_cursor = Qt::ArrowCursor;

    _switch.insert("stretch-move-enable", true);
    _switch.insert("rvs_animat_end", true);
    _switch.insert("msev_rls", true);

    installEventFilter(this);
    connect(&blurTimer, &QTimer::timeout, this, &NMainWindow::opacityTimer);
    connect(&stretchTimer, &QTimer::timeout, this, [this](){window_change_stretch();});
    connect(TT_Object, &NTitleBar::tt_cdmsev_rls, this, &NMainWindow::d_caption_press);
    connect(TT_Object, &NTitleBar::tt_msev_mv, this, [this](QPoint pos){notify(NTitleBar::Mouse_Move, pos);});
    connect(TT_Object, &NTitleBar::tt_msev_rls, this, [this](QPoint pos){notify(NTitleBar::Mouse_Release, pos);});
    connect(TT_Object, &NTitleBar::tt_msev_pre, this, [this](QPoint pos){notify(NTitleBar::Mouse_Press, pos);});
    connect(TT_Object, &NTitleBar::tt_ico_pre, this, &NMainWindow::bsic_icopre);
    connect(TT_Object, &NTitleBar::tt_msev_etr, this, &NMainWindow::enterEvent);
    connect(TT_Object, &NTitleBar::tt_msev_lev, this, &NMainWindow::leaveEvent);
    connect(TT_Object, &NTitleBar::tt_msev_nrrls, this, &NMainWindow::bsic_nrrls);
    connect(TT_Object, &NTitleBar::tt_msev_db, this, [this](){notify(NTitleBar::Mouse_Double);});
    connect(TT_Object, &NTitleBar::tt_hover_mv, this, &NMainWindow::eventFilterT);
    connect(TT_Object, &NTitleBar::tt_ttxt_pre, this, &NMainWindow::bsic_ttlepre);
    connect(View_hoverMask, &FloatingWindow::msev_rls, this, &NMainWindow::hover_release_event);
    connect(backAnimationGroup, &QParallelAnimationGroup::finished, this, &NMainWindow::animation_running_end);

}

NMainWindow::~NMainWindow(){
    delete View_shadowMask;
    delete View_hoverMask;
    delete Animainback;
    delete Animacpback;
    delete backAnimationGroup;
}

void NMainWindow::winmvAndstretchOff(bool enable){
    _switch.insert("stretch-move-enable", enable);
}

void NMainWindow::d_painter_effectrange(QRect _range, QList<QColor> _flrcolor){
    effect_range = _range;
    back_color_map["filler_color"] = _flrcolor;
}

void NMainWindow::d_filler_color(QList<QColor> color){
    back_color_map["standar_color"].swap(color);
}

void NMainWindow::d_filler_color(QColor color){
    back_color_map["standar_color"] = {color};
}

void NMainWindow::d_filler_color(QString color){
    back_color_map["standar_color"] = {QColor(color)};
}

void NMainWindow::d_filler_pixmap(QString curtain){
    if (!back_pixmap.load(curtain))
    {
        back_pixmap.loadFromData(QByteArray::fromBase64(curtain.toLocal8Bit()));
    }
    else
    {
        back_pixmap.load(curtain);
    }
}

void NMainWindow::d_floating_pixmap(QString curtain){
    View_hoverMask->setCurtain(curtain);
}

void NMainWindow::d_filler_orientation(NT::CST_BRIGHT_SPOT orien){
    linear_orien = orien;
}

void NMainWindow::d_filler_enable(NTitleBar::FillerType Type, bool Enable){
    QList<NTitleBar::FillerType> keys = RdoMap_FillerType.keys();
    foreach(NTitleBar::FillerType type, keys) RdoMap_FillerType[type] = false;
    RdoMap_FillerType.insert(Type, Enable);
}

void NMainWindow::d_filler_clear(NTitleBar::FillerType Type){
    if (Type == NTitleBar::FillerType::BACKCOLOR)
    {
        back_color_map["standar_color"].clear();
    }
    else if (Type == NTitleBar::FillerType::BACKPIXMAP)
    {
        back_pixmap = QPixmap();
    }
}

void NMainWindow::d_margin_radius(QMargins margin, int radius){
    win_radius = radius;
    setContentsMargins(margin);
    update();
}

void NMainWindow::close(){
    TT_Object->close();
    QMainWindow::close();
}

void NMainWindow::setVisible(bool visible){
    QMainWindow::setVisible(visible);
    TT_Object->setVisible(visible);
    if (init_win_rect.isNull()) init_win_rect = geometry();
    accept_minsize = minimumSizeHint();
    accept_capminsize = TT_Object->minimumSizeHint();
    window_change_centra();
    window_change_catchup();
}

bool NMainWindow::eventFilter(QObject *watched, QEvent *Event){
    QList<QEvent::Type> acceptTypes({QEvent::HoverMove,
                                     QEvent::MouseButtonPress,
                                     QEvent::MouseButtonRelease});
    if (acceptTypes.contains(Event->type()))
    {
        QMouseEvent *mouseEv = static_cast<QMouseEvent*>(Event);
        if (Event->type() == QEvent::HoverMove)
        {
            if (ms_start.isNull())
            {
                if (_switch["stretch-move-enable"]) eventFilterT(mouseEv->pos());
            }
            else
            {
                if (margin_touch_type != NT::LOCALTION::LOCALTION_UNVALID && _switch["stretch-move-enable"]) notify(NTitleBar::Mouse_Move, mouseEv->pos());
            }
        }
        if (mouseEv->button() == Qt::LeftButton &&
            !mouseEv->pos().isNull() &&
            Event->type() == QEvent::MouseButtonPress)
        {
            notify(NTitleBar::Mouse_Press, mouseEv->pos());
        }
        if (mouseEv->button() == Qt::LeftButton &&
            Event->type() == QEvent::MouseButtonRelease)
        {
            notify(NTitleBar::Mouse_Release, mouseEv->pos());
        }
    }
    if (Event->type() == QEvent::Resize)
    {
        if (_switch["rvs_animat_end"]) window_change_catchup();
        if (!back_pixmap.isNull())
        {
            back_pixmap = back_pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        }
        update();
    }
    return QMainWindow::eventFilter(watched, Event);
}

void NMainWindow::eventFilterT(QPoint _pos){
    int consult_corner;
    win_radius ? consult_corner = win_radius : consult_corner = win_cornered;
    NT::LOCALTION temporaty_margin_type = marginsTouch(_pos, consult_corner / 2, 2);
    if (_switch["msev_rls"])
    {
        margin_touch_type = temporaty_margin_type;
    }
    //# 移动或者拉伸过程中，不赋值，因为拉伸或移动过程中，鼠标经过窗口边缘，会发生误赋值
    switch (margin_touch_type)
    {
        case NT::LOCALTION_CENTER_ROOF:
            TT_Object->setCursor(Qt::SizeVerCursor);
            break;
        case NT::LOCALTION_CENTER_BOTTON:
            setCursor(Qt::SizeVerCursor);
            break;
        case NT::LOCALTION_CENTER_RIGHT:
        case NT::LOCALTION_CENTER_LEFT:
            TT_Object->setCursor(Qt::SizeHorCursor);
            setCursor(Qt::SizeHorCursor);
            break;
        case NT::LOCALTION_BOTTON_LEFT:
            setCursor(Qt::SizeBDiagCursor);
            break;
        case NT::LOCALTION_ROOF_RIGHT:
            TT_Object->setCursor(Qt::SizeBDiagCursor);
            break;
        case NT::LOCALTION_ROOF_LEFT:
            TT_Object->setCursor(Qt::SizeFDiagCursor);
            break;
        case NT::LOCALTION_BOTTON_RIGHT:
            setCursor(Qt::SizeFDiagCursor);
            break;
    default:
        setCursor(move_cursor);
        TT_Object->setCursor(move_cursor);
    }
}

NTitleBar* NMainWindow::captionBar(){
    return TT_Object;
}

void NMainWindow::paintEvent(QPaintEvent *){
    QPainter captainPainter(this);
    QPainterPath path;
    captainPainter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    QRect drawrect = rect().adjusted(0, -win_radius, 0, 0);
    path.addRoundedRect(drawrect, win_radius, win_radius);
    captainPainter.setClipPath(path);
    captainPainter.setPen(Qt::NoPen);
    QList<QColor> standar_colors = back_color_map["standar_color"];
    QList<QColor> filler_colors = back_color_map["filler_color"];
    int rang_w = effect_range.width();
    int rang_h = effect_range.height();
    QRect realrect = captainPainter.viewport();
    QRect offectrect;
    if (!filler_colors.isEmpty())
    {
        TT_Object->painterLinear(captainPainter, realrect, linear_orien, filler_colors);
    }

    if (RdoMap_FillerType[NTitleBar::FillerType::BACKCOLOR])
    {
        int apply_w = rang_w;
        int apply_y = rang_h;
        if (!rang_w) apply_w = realrect.width();
        if (!rang_h) apply_y = realrect.height();
        offectrect = QRect(effect_range.x(), effect_range.y(), apply_w, apply_y);
    }
    else
    {
        offectrect = captainPainter.viewport();
    }

    if (RdoMap_FillerType[NTitleBar::FillerType::BACKCOLOR] && !standar_colors.isEmpty())
    {
        TT_Object->painterLinear(captainPainter, offectrect, linear_orien, standar_colors);
    }
    else if (RdoMap_FillerType[NTitleBar::FillerType::BACKPIXMAP] && !back_pixmap.isNull())
    {
        captainPainter.drawPixmap(offectrect, back_pixmap);
    }
}

void NMainWindow::window_change_start(QPoint mvp){

    if (View_shadowMask->isVisible())
    {
        if (margin_touch_type == NT::LOCALTION_UNVALID)
        {
            QPoint tt_pos = TT_Object->pos() + mvp;
            QRect mvrect(tt_pos.x(), tt_pos.y(), width(), height() + captionBar()->height());
            View_shadowMask->doUpdate(mvrect);
        }
        else
        {
            window_change_stretch(mvp);
        }
    }
    else
    {
        View_shadowMask->setVisible(true);
    }
}

void NMainWindow::window_change_end(){
    alte_win_rect = View_shadowMask->inneRect.adjusted(0, captionBar()->height(), 0, 0);
    if (margin_touch_type == NT::LOCALTION_UNVALID)
    {
        window_change_catchup();
        QRect readyRect(alte_win_rect.adjusted(0, - captionBar()->height(), 0, 0));
        bool isTouch = View_hoverMask->captureMargin(readyRect);
        if (isTouch)
        {
            _switch["rvs_show"] = true; // 设置渐变隐藏对象为主窗口，显示对象为悬停窗口
            View_hoverMask->run();
            blurTimer.setInterval(rvs_hinteval);
            blurTimer.start();
        }
        else
        {
            TT_Object->setWindowOpacity(0);
            setWindowOpacity(0);
            stretchTimer.start();
        }
    }
    else
    {
        TT_Object->setWindowOpacity(0);
        setWindowOpacity(0);
        stretchTimer.start();
    }
    View_shadowMask->setVisible(false);
    emit bsic_posmv();
}

void NMainWindow::window_change_centra(){
    QRect Sysrect = geometry();
    int Rm_x = (desktop_mask->size().width() - Sysrect.width()) / 2;
    int Rm_y  = (desktop_mask->size().height() - Sysrect.height()) / 2;
    QPoint win_pos = QPoint(Rm_x, Rm_y);
    move(win_pos);
}

void NMainWindow::window_change_catchup(){
    QRect _rect = geometry();
    QRect TT_geometry(_rect.x(), _rect.y() - captionBar()->height(), _rect.width(), captionBar()->height());
    TT_Object->setGeometry(TT_geometry);
}

void NMainWindow::caption_batcatch_up(){
    QRect _rect = TT_Object->geometry();
    QRect Maingeometry(_rect.x(), _rect.y() + captionBar()->height(), width(), height());
    setGeometry(Maingeometry);
}

void NMainWindow::window_change_stretch(){
    setGeometry(alte_win_rect);
    window_change_catchup();
    _switch["rvs_show"] = false;
    blurTimer.setInterval(exp_sinteval);
    blurTimer.start();
}

void NMainWindow::window_change_stretch(QPoint mvp){
    long mv_x = mvp.x(); //#该值不可abs，会有无限大异常
    long mv_y = mvp.y();
    int w = size().width();
    int h = size().height();
    int gmt_x;
    int gmt_y;
    int sz_w;
    int sz_h;
    if (margin_touch_type == NT::LOCALTION_ROOF_LEFT)
    {
        gmt_x = pos().x() + mv_x;
        gmt_y = pos().y() + mv_y;
        sz_w = w - mv_x;
        sz_h = h - mv_y;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else if (margin_touch_type == NT::LOCALTION_CENTER_ROOF)
    {
        gmt_x = pos().x();
        gmt_y = pos().y() + mv_y;
        sz_w = w;
        sz_h = h - mv_y;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else if (margin_touch_type == NT::LOCALTION_ROOF_RIGHT)
    {
        gmt_x = pos().x();
        gmt_y = pos().y() + mv_y;
        sz_w = w + mv_x;
        sz_h = h - mv_y;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else if (margin_touch_type == NT::LOCALTION_CENTER_RIGHT)
    {
        gmt_x = pos().x();
        gmt_y = pos().y();
        sz_w = w + mv_x;
        sz_h = h;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else if (margin_touch_type == NT::LOCALTION_BOTTON_RIGHT)
    {
        gmt_x = pos().x();
        gmt_y = pos().y();
        sz_w = w + mv_x;
        sz_h = h + mv_y;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else if (margin_touch_type == NT::LOCALTION_CENTER_BOTTON)
    {
        gmt_x = pos().x();
        gmt_y = pos().y();
        sz_w = w;
        sz_h = h + mv_y;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else if (margin_touch_type == NT::LOCALTION_BOTTON_LEFT) //# x-y+
    {
        gmt_x = pos().x() + mv_x;
        gmt_y = pos().y();
        sz_w = w - mv_x;
        sz_h = h + mv_y;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
    else
    {
        gmt_x = pos().x() + mv_x;
        gmt_y = pos().y();
        sz_w = w - mv_x;
        sz_h = h;
        window_change_stretchq(gmt_x, gmt_y, sz_w, sz_h);
    }
}

void NMainWindow::window_change_stretchq(int x, int y, int w, int h){
    if (w >= accept_minsize.width() &&
        w >= accept_capminsize.width() &&
        h >= accept_minsize.height() &&
        h >= accept_capminsize.height())
    {
        View_shadowMask->doUpdate(QRect(x, y, w, h).adjusted(0, - captionBar()->height(), 0, 0));
    }
}

void NMainWindow::d_caption_press(NTitleBar::BasicButtom buttom){
    int screenWidth = desktop_mask->size().width();
    int screenHeight = desktop_mask->size().height();
    QRect maxwin(0, captionBar()->height(), screenWidth, screenHeight - captionBar()->height() - taskbar_height);
    switch (buttom)
    {
        case NTitleBar::Rroof_Normal:
            if (!init_win_rect.isNull())
            {
                setGeometry(init_win_rect);
                window_change_catchup();
                emit bsic_posmv(); //补充移动事件
            }
            break;
        case NTitleBar::Rroof_Min:
            showMinimized();
            break;
        case NTitleBar::Rroof_Max:
            if (size() == maxwin.size())
            {
                setGeometry(wmax_ago_rect);
            }
            else
            {
                wmax_ago_rect = geometry();
                setGeometry(maxwin);
            }
            window_change_catchup();
            break;
        case NTitleBar::Rroof_Exit:
            emit bsic_quit();
            break;
    }
}

void NMainWindow::notify(NTitleBar::ButtomType buttomType, QPoint event_pos){
    bool mvassert;
    switch (buttomType)
    {
        case NTitleBar::Mouse_Press:
            ms_start = event_pos;
            near_win_rect = geometry();
            _switch["msev_rls"] = false;
            break;
        case NTitleBar::Mouse_Release:
            if (!ms_move.isNull()) window_change_end();
            ms_start = QPoint(0, 0);
            ms_move = QPoint(0, 0);
            _switch["msev_rls"] = true;
            break;
        case NTitleBar::Mouse_Move:
            mvassert = (!ms_start.isNull() && ms_start != event_pos && _switch["stretch-move-enable"]);
            try
            {//ms_start 、ms_move 皆有可能为空
                if (mvassert) ms_move = event_pos - ms_start;
            }
            catch (std::exception &Error)
            {
                ms_start = QPoint(0, 0);
            }
            if (mvassert) window_change_start(ms_move); //修复异常渐变显示的问题，原因为ms_move x/y < 0 || x/y || < 1,异常触发
            break;
        case NTitleBar::Mouse_Double:
            if (geometry().width() == desktop_mask->geometry().width() ||
                geometry().height() == desktop_mask->geometry().height())
            {
                d_caption_press(NTitleBar::Rroof_Normal);
            }
            else
            {
                d_caption_press(NTitleBar::Rroof_Max);
            }
            break;
    }
}

void NMainWindow::hover_release_event(){

    _switch["rvs_show"] = false;
    _switch["rvs_animat_end"] = false;
    blurTimer.setInterval(rvs_sinteval);
    Animacpback->setStartValue(QRect(View_hoverMask->x(),
                                   View_hoverMask->y(),
                                   minimumSizeHint().width(),
                                   captionBar()->height()));
    Animacpback->setEndValue(QRect(near_win_rect.x(),
                                 near_win_rect.y() - captionBar()->height(),
                                 near_win_rect.width(),
                                 captionBar()->height()));
    Animacpback->setDuration(linear_backtime);
    Animainback->setStartValue(QRect(View_hoverMask->x(),
                                     View_hoverMask->y(),
                                     minimumSizeHint().width(),
                                     minimumSizeHint().height()));
    near_win_rect.isNull() ? Animainback->setEndValue(init_win_rect) : Animainback->setEndValue(near_win_rect);
    Animainback->setDuration(linear_backtime);
    backAnimationGroup->addAnimation(Animacpback);
    backAnimationGroup->addAnimation(Animainback);
    backAnimationGroup->start();
    blurTimer.start();

}

void NMainWindow::opacityTimer(){
    rvs_scount += 1;
    rvs_hcount -= 1;
    if (_switch["rvs_show"])
    {
        //View_hoverMask 不合适构造的去visible，因为需要附带把窗口透明度设置为0，不影响功能实现，但会影响父类的圆角绘制，导致圆角失效
        if (!View_hoverMask->isVisible()) View_hoverMask->setVisible(true);
        View_hoverMask->setWindowOpacity(rvs_scount / 10.0);
        TT_Object->setWindowOpacity(rvs_hcount / 10.0);
        setWindowOpacity(rvs_hcount / 10.0);
    }
    else
    {
        View_hoverMask->setWindowOpacity(rvs_hcount / 10.0);
        TT_Object->setWindowOpacity(rvs_scount / 10.0);
        setWindowOpacity(rvs_scount / 10.0);
        activateWindow();
    }
    if (rvs_scount == 10 && rvs_hcount == 0)
    {
        rvs_scount = 0;
        rvs_hcount = 10;
        blurTimer.stop();
    }
}

void NMainWindow::d_cursor(QCursor cursor){
    move_cursor.swap(cursor);
}

void NMainWindow::animation_running_end(){
    _switch["rvs_animat_end"]=true;
    emit bsic_posmv();
}

NT::LOCALTION NMainWindow::marginsTouch(QPoint _pos, int radius, int pardonValue){
    //# 顶部指针形状针对标题栏对象，而不是主窗口，因此主窗口y=0影响判断，y<0 时已切换标题栏区域，避开误判
    int mvx = _pos.x();
    int mvy = _pos.y();
    int gx = rect().x();
    int gy = rect().y();
    int gw = rect().width();
    int gh = rect().height();
    bool roof = (mvy <= gy + pardonValue) || (mvy <= gy - pardonValue);
    bool down = (mvy >= gy + gh - pardonValue) || (mvy >= gy + gh + pardonValue);
    bool left = (mvx <= gx + pardonValue) || (mvx <= gx - pardonValue);
    bool right = (mvx >= gx + gw - pardonValue) || (mvx >= gx + gw + pardonValue);
    bool lr = (mvx <= gx + radius && mvy <= gy + radius) || (mvx <= gx - radius && mvy <= gy - radius);
    bool rr = (mvx >= gx + gw - radius && mvy <= gy + radius) || (mvx >= gx + gw + radius && mvy <= gy - radius);
    bool lb = (mvx <= gx + radius && mvy >= gy + gh - radius) || (mvx <= gx - radius && mvy >= gy + gh + radius);
    bool rb = (mvx >= gx + gw - radius && mvy >= gy + gh - radius) || (mvx >= gx + gw + radius && mvy >= gy + gh + radius);
    if (lr) return NT::LOCALTION_ROOF_LEFT; // 0
    else if (rr) return NT::LOCALTION_ROOF_RIGHT; // 2
    else if (rb) return NT::LOCALTION_BOTTON_RIGHT; // 4
    else if (lb) return NT::LOCALTION_BOTTON_LEFT; // 6
    else if (roof && !down && !left && !right) return NT::LOCALTION_CENTER_ROOF; // 1
    else if (!roof && !down && !left && right) return NT::LOCALTION_CENTER_RIGHT; // 3
    else if (!roof && down && !left && !right) return NT::LOCALTION_CENTER_BOTTON; // 5
    else if (!roof && !down && left && !right) return NT::LOCALTION_CENTER_LEFT; // 7
    else return NT::LOCALTION_UNVALID; // 8
}

void NMainWindow::move(int ax, int ay){
    QMainWindow::move(ax, ay);
    window_change_catchup();
}

void NMainWindow::move(QPoint point){
    QMainWindow::move(point);
    window_change_catchup();
}

void NMainWindow::resize(int w, int h){
    QMainWindow::resize(w, h - TT_Object->height());
}

void NMainWindow::resize(const QSize &size){
    QMainWindow::resize(size - QSize(0, TT_Object->height()));
}

void NMainWindow::setFixedHeight(int h){
    QMainWindow::setFixedHeight(h - TT_Object->height());
}

void NMainWindow::setFixedSize(int w, int h){
    QMainWindow::setFixedSize(w, h - TT_Object->height());
}

void NMainWindow::setMaximumHeight(int maxh){
    QMainWindow::setMaximumHeight(maxh - TT_Object->height());
}

void NMainWindow::setMinimumHeight(int minh){
    QMainWindow::setMinimumHeight(minh - TT_Object->height());
}

void NMainWindow::setMaximumSize(int maxw, int maxh){
    QMainWindow::setMaximumSize(maxw, maxh - TT_Object->height());
}

void NMainWindow::setMaximumSize(const QSize &s){
    QMainWindow::resize(s - QSize(0, TT_Object->height()));
}

void NMainWindow::setMinimumSize(int minw, int minh){
    QMainWindow::setMaximumSize(minw, minh - TT_Object->height());
}

void NMainWindow::setMinimumSize(const QSize &s){
    QMainWindow::resize(s - QSize(0, TT_Object->height()));
}

//================MessageBoxQ
MessageBoxQ::MessageBoxQ(QWidget *_this_,
                         QList<QString> options,
                         int MessageBoxQType,
                         QString scdr_mesage,
                         QString main_mesage,
                         QVariant content_backcolor,
                         QVariant caption_backcolor) :
    iotionsNum(options.size())
    {
        Type messageType = static_cast<Type>(MessageBoxQType);
        delayShowTimer.setInterval(30);
        delayShowTimer.setSingleShot(true);

        setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
        QMap<Type, QString> typeMap({{MessageBoxQ::MSG_Dedly, ":/PIXMAP/bench/message-dedly.png"},
                                     {MessageBoxQ::MSG_Error, ":/PIXMAP/bench/message-error.png"},
                                     {MessageBoxQ::MSG_Question, ":/PIXMAP/bench/message-question.png"},
                                     {MessageBoxQ::MSG_Info, ":/PIXMAP/bench/message-info.png"},
                                     {MessageBoxQ::MSG_Warning, ":/PIXMAP/bench/message-warning.png"}});

        main_vbox->addWidget(message_text);
        main_vbox->addLayout(bottom_vbox);
        main_vbox->setSpacing(10);
        bottom_vbox->setSpacing(2);
        setMaximumWidth(500);
        message_text->setWordWrap(true);
        message_text->setStyleSheet("QLabel{text-align: center; "
                                    "background-color:transparent; "
                                    "font-family: KaiTi_GB2312; "
                                    "font: 15px;"
                                    "border:0px;}");
        message_text->setText(main_mesage);

        switch (messageType) {

            case MSG_Question:
                captionBar()->d_caption(scdr_mesage, QFont("KaiTi_GB2312", 12), QColor(64,169,255));
                break;
            case MSG_Dedly:
                captionBar()->d_caption(scdr_mesage, QFont("KaiTi_GB2312", 12), QColor(255,0,0));
                break;
            case MSG_Error:
                captionBar()->d_caption(scdr_mesage, QFont("KaiTi_GB2312", 12), QColor(255,92,92));
                break;
            case MSG_Info:
                captionBar()->d_caption(scdr_mesage, QFont("KaiTi_GB2312", 12), QColor(0,200,0));
                break;
            case MSG_Warning:
                captionBar()->d_caption(scdr_mesage, QFont("KaiTi_GB2312", 12), QColor(208,224,0));
                break;
        }

        d_margin_radius(QMargins(3, 0, 3, 0), 8);
        captionBar()->d_captionico(typeMap[messageType], 1.1, 4);
        captionBar()->d_filler_enable(NTitleBar::FillerType::BACKPIXMAP, true); //设置标题栏填充为背景色模式
        captionBar()->d_basicbuttom_configur(NT::PIXLOAD_IGNORERATIO_LOWER, NT::DRAWTYPE_ROUND, 3, 1.5); //设置绘画类型为矩形，边距为1
        captionBar()->d_basicbuttom_freepixmap(NTitleBar::QUITE, 5, qRgb(242,241,247)); //设置关闭按钮背景图
        captionBar()->d_basicbuttom_where({NTitleBar::Rroof_Max,
                                           NTitleBar::Rroof_Min,
                                           NTitleBar::Rroof_Max,
                                           NTitleBar::Rroof_Normal}, false);
        captionBar()->d_basicbuttom_where(NTitleBar::Rroof_Exit, {QString(MSEVKEY.WIN_NORMAL),QString(MSEVKEY.WIN_LEAVE)});
        connect(this, &MessageBoxQ::bsic_quit, this, [this](){close();});
        connect(&delayShowTimer, &QTimer::timeout, this, [&](){setWindowOpacity(0);
                                                               shadoMask->setVisible(true);
                                                               setVisible(true);
                                                               int newx = _prt_x + _prt_w / 2 - width() / 2;
                                                               int newy = _prt_y + _prt_h / 2 - (height() + captionBar()->height()) / 2;
                                                               move(newx, newy);
                                                               setWindowOpacity(1);});
        backparser(captionBar(), caption_backcolor);
        backparser(this, content_backcolor);
        _prt_x = _this_->x();
        _prt_y = _this_->y();
        _prt_w = _this_->width();
        _prt_h = _this_->height();
        setCentralWidget(global_pwidget);
        delayShowTimer.start();
        setOptions(options);
}

void MessageBoxQ::setOptions(QList<QString> options){
    int row = 0; //行数
    int cache = 4; //组件宽缓和值
    int addtion = 0; //组件数量累加值
    int adjustwidth = 0; //最优组件宽(理论)
    int specingwidth = 0; //布局缝隙统计值
    bool ismakeup = false; //是否布局组件宽(实施)
    bool isoverange = false; //组件宽是否超限
    if (!options.isEmpty()){
        globalFont.setPointSize(globalFont.pointSize() - 4);
        QFontMetrics metrics(globalFont);
        int loop = options.size();
        for (int index = 0; index < loop; index++){
            QString sctObjectName = QString::number(index);
            NPushButton * temporaryBut = new NPushButton(this);
            temporaryBut->setStyleSheet("QPushButton{"
                                        "outline:none;"
                                        "font:14px;"
                                        "color:rgb(110,110,110);"
                                        "border-radius:2px;"
                                        "background-color:rgb(228,226,239);}"

                                        "QPushButton:pressed{"
                                        "outline:none;"
                                        "font:14px;"
                                        "color:rgb(25,25,25);"
                                        "border-radius:2px;"
                                        "background-color:rgb(200,197,222);}"

                                        "QPushButton:hover{"
                                        "color:rgb(49,49,49);"
                                        "border-radius:2px;"
                                        "border: 1px solid rgb(161,153,197);}");
            temporaryBut->setText(options[index]);
            temporaryBut->setFont(globalFont);
            temporaryBut->setObjectName(sctObjectName);
            temporaryBut->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
            temporaryBut->setContentsMargins(2, 2, 2, 2);
            temporaryBut->setFixedHeight(23);
            int main_marginboth = contentsMargins().left() + contentsMargins().right(); //主窗口左右边距
            int extra_marginboth = global_pwidget->contentsMargins().left() + global_pwidget->contentsMargins().right();//子窗口左右边距
            int sizetextwidth = metrics.horizontalAdvance(options[index]); //理论组件文本宽
            if (adjustwidth < sizetextwidth) adjustwidth = sizetextwidth + cache; //获取最大组件宽理论值
            addpushbuttom(row, addtion); //增加水平布局，不附加组件
            specingwidth = layoutmap[row]->spacing() * (addtion - 1);
            int bestlayoutnum = floor((width() - specingwidth - extra_marginboth - main_marginboth) / (double)adjustwidth);//但水平布局最优理论组件数
            isoverange = addtion >= bestlayoutnum; //是否超限
            connect(temporaryBut, &NPushButton::msnm_rls, this, &MessageBoxQ::mouseCheckEvent);
            if (layoutmap[row]) //有布局时添加组件
            {
                if (!isoverange) //不超限，添加组件，情景 A
                {
                    layoutmap[row]->addWidget(temporaryBut, 0, Qt::AlignCenter);
                    addtion++;
                }
                //如果当前组件为最后一个组件，并且没有超限，即水平布局添加这些组件后没有条件触发最优组件宽的设置，则赋予例外条件(针对)
                if (index == loop - 1 && !isoverange) ismakeup = true;
                if (isoverange || ismakeup) // 有布局并且总布局宽度超限时或者例外条件标志为true时，分配上一个布局的组件宽
                {
                    for(int layout_index = 0;layout_index < layoutmap[row]->count(); layout_index++) //布局的组件数
                    {
                        QPushButton *childBut = static_cast<QPushButton*>(layoutmap[row]->itemAt(layout_index)->widget());
                        if (childBut)
                        {
                            if (addtion)
                            {
                                int lastwidth = (width() - main_marginboth - extra_marginboth - specingwidth) / addtion;
                                childBut->setFixedWidth(lastwidth);
                            }
                        }
                    }
                    row++;
                    addtion = 0;
                    adjustwidth = 0;
                    ismakeup = false;
                }
                //补足情景 A，形成回路，超限的情况下组件的添加(超限是 row +1，该代表在row作该表后重起水平布局添加组件，但 index == loop - 1 时会伴随着组件宽无法得到处理的问题)
                if (isoverange)
                {
                    addpushbuttom(row, addtion, temporaryBut);
                    if (addtion)
                    {   //补足 index == loop - 1 时的情况，index != loop - 1时，会有下次循环触发 index == loop - 1 && !isoverange，引发重新布局
                        //而 index == loop - 1
                        int lastwidth = (width() - main_marginboth - extra_marginboth) / addtion;
                        temporaryBut->setFixedWidth(lastwidth);
                    }
                }
            }
        }
    }
}

void MessageBoxQ::addpushbuttom(int &_row, int &_addtion, QPushButton *_buttom){
    if (!layoutmap[_row]) //无布局时创建
    {
        if (_buttom)
        {
            layoutmap[_row] = new QHBoxLayout();
            layoutmap[_row]->setSpacing(2);
            bottom_vbox->addLayout(layoutmap[_row]);
            layoutmap[_row]->addWidget(_buttom, 0, Qt::AlignCenter); _addtion++;
        }
        else
        {
            layoutmap[_row] = new QHBoxLayout();
            layoutmap[_row]->setSpacing(2);
            bottom_vbox->addLayout(layoutmap[_row]);
        }
    }
}

void MessageBoxQ::mouseCheckEvent(QString objectName){
    QPushButton *checkBut = findChild<QPushButton*>(objectName);
    emit checkEvent(checkBut);
    shadoMask->close();
    close();
}

MessageBoxQ::~MessageBoxQ(){
    delete message_text;
    delete bottom_vbox;
    delete global_pwidget;
    delete shadoMask;
    for(int index=0; index < iotionsNum; index++)
    {
        delete findChild<QPushButton*>(QString::number(index));
    }
}
